package gagak.framework.web.context;

import gagak.framework.web.adapter.HandlerAdapter;
import gagak.framework.web.adapter.RequestMappingMethodAdapter;
import gagak.framework.web.annonation.RequestMapping;
import gagak.framework.web.exception.HxWebException;
import gagak.framework.web.handler.ControllerHandler;
import gagak.framework.web.handler.HandlerMapping;
import gagak.framework.web.handler.RequestMappingHandlerMapping;
import gagak.framework.web.param.HandlerMethod;
import gagak.framework.web.paramresovler.*;
import gagak.framework.web.paramresovler.converter.HandlerMethodReturnValueHandler;
import gagak.framework.web.paramresovler.requestbody.HttpMessageConverter;
import gagak.framework.web.paramresovler.requestparam.RequestParamMethodArgumentResolver;
import gagak.framework.web.paramresovler.requestresponse.ServletRequestMethodArgumentResolver;
import gagak.framework.web.paramresovler.requestresponse.ServletResponseMethodArgumentResolver;
import gagak.framework.web.reflect.AnnotationAttributes;
import gagak.framework.web.reflect.AnnotationUtils;
import gagak.framework.web.utils.CollectionUtils;
import gagak.framework.web.utils.ObjectUtils;
import gagak.framework.web.utils.StringUtils;
import gagak.framework.web.view.FastJsonViewResolver;
import gagak.framework.web.view.View;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;


/*
 * @program: ce
 * @description: 初始化容器组件  把requestBody做了
 * @author: houhong
 * @create: 2022-11-24 19:54
 */
public abstract class AbstractApplicationContext implements ApplicationContext {


    private static final Logger logger = LoggerFactory.getLogger(AbstractApplicationContext.class);
    //所有的映射器
    protected List<HandlerMapping> handlerMappings;
    //所有的适配器
    protected List<HandlerAdapter> handlerAdapters;

    //所有的参数解析器
    protected List<HandlerMethodArgumentResolver> handlerMethodArgumentResolvers;

    protected List<HandlerMethodReturnValueHandler> handlerMethodReturnValueHandlers;
    // 视图解析器
    protected List<View> viewResolvers;

    @Override
    public void initApplication() {

        //初始化映射器类
        initHandlerMapping();
        //初始化适配器
        initHandlerApater();
        //初始化参数解析器
        initHandlerArguments();
        //初始化视图解析器
        initViewResoulvers();
    }


    /*
     * 初始化handlerMapping 映射器
     */
    public void initHandlerMapping() {

        if (CollectionUtils.isEmpty(handlerMappings)) {
            handlerMappings = new ArrayList<HandlerMapping>(4);
            RequestMappingHandlerMapping innerRmhp = new RequestMappingHandlerMapping();
            handlerMappings.add(innerRmhp);
        }

    }

    /*
     * 初始化handlerapater -- 默认只有一种 RequestMappingMethodAdapter
     */
    public void initHandlerApater() {

        if (CollectionUtils.isEmpty(handlerAdapters)) {

            handlerAdapters = new ArrayList<HandlerAdapter>(4);
            RequestMappingMethodAdapter innerRmmdap = new RequestMappingMethodAdapter();
            handlerAdapters.add(innerRmmdap);
        }
    }


    /*
     * 初始化内置的参数解析器组件
     */
    public void initHandlerArguments() {


        if (CollectionUtils.isEmpty(handlerMethodArgumentResolvers)) {

            handlerMethodArgumentResolvers = new ArrayList<HandlerMethodArgumentResolver>(4);
            //初始化所有的参数解析器
            //1 ：HttpServletRequestd的解析器
            ServletRequestMethodArgumentResolver requestMethodArgumentResolver = new ServletRequestMethodArgumentResolver();
            handlerMethodArgumentResolvers.add(requestMethodArgumentResolver);
            // 2: 解析HttpServletResponse的
            ServletResponseMethodArgumentResolver responseMethodArgumentResolver = new ServletResponseMethodArgumentResolver();
            handlerMethodArgumentResolvers.add(responseMethodArgumentResolver);
            //解析@RequestParam的
            RequestParamMethodArgumentResolver requestParamMethodArgumentRrs = new RequestParamMethodArgumentResolver(false);
            handlerMethodArgumentResolvers.add(requestParamMethodArgumentRrs);

            //解析@RequestBody的
            List<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<HttpMessageConverter<?>>();
            // 添加jsonConverter // TODO: 2022/12/2
          /*  httpMessageConverters.add(new MappingJackson2HttpMessageConverter());
            RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor = new RequestResponseBodyMethodProcessor(httpMessageConverters);
            handlerMethodArgumentResolvers.add(requestResponseBodyMethodProcessor);*/
        }
        //返回参数解析器  // TODO: 2022/12/1   不需要 --- 放在DispatchServlet里面处理

    }

    /*
     * 初始化内置的视图解析器组件
     */
    public void initViewResoulvers() {
        if (CollectionUtils.isEmpty(viewResolvers)) {

            viewResolvers = new CopyOnWriteArrayList<View>();
            //添加数据
            View jsonViewSolver = new FastJsonViewResolver();
            viewResolvers.add(jsonViewSolver);
        }
    }

    /*============================一些类元信息处理，用于对类进行获取================================*/


    /*
     * @param classLoader
     * @param clazz
     * @return
     * @Author houhong
     * @Description //TODO  用于获取类上的信息，并且处理成AnnoationAttributes
     * @Date 8:56 下午 2022/11/24
     */
    protected ControllerHandler getClassAnnotationInfo(ClassLoader classLoader, String clazz) throws HxWebException {

        //控制器类
        ControllerHandler controllerHandler = null;
        // 非空判断
        if (StringUtils.isEmpty(clazz) || ObjectUtils.isEmpty(classLoader)) {
            return null;
        }

        try {

            Class<?> aClass = classLoader.loadClass(clazz);

            // // TODO: 2022/11/24  先做一版实现的 后面再优化
            controllerHandler = new ControllerHandler(aClass);

            if (ObjectUtils.isEmpty(controllerHandler.getController())) {
                //实列化一个
                controllerHandler.setController(aClass.newInstance());
            }
            //解析requestMapping
            parseRequestMapping(aClass, controllerHandler);
            //获取方法
            getMethods(aClass, controllerHandler);

        } catch (Throwable e) {
            logger.error("【mvc-framework】parse controller encounter error :\n{}", e);
            throw new HxWebException("pase controller error");
        } finally {

        }

        //设置class
        return controllerHandler;
    }


    /*
     * 解析requestMapping
     */
    public AnnotationAttributes parseRequestMapping(Class<?> clazz, ControllerHandler controllerHandler) {

        RequestMapping requestMapping = AnnotationUtils.findAnnotation(clazz, RequestMapping.class);
        requestMapping.annotationType();
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        String path = requestMapping.path();
        //路径
        if (!StringUtils.isEmpty(path)) {
            map.put("path", path);
        }
        //设置路径
        controllerHandler.setPath(path);

        AnnotationAttributes annotationAttributes = new AnnotationAttributes(map, requestMapping.annotationType());
        controllerHandler.addAnnotationAttributesMap(requestMapping, annotationAttributes);
        return annotationAttributes;
    }


    /*
     * 获取所有的带有@RequrstMapping 公开的方法
     */
    public Method[] getMethods(Class<?> clazz, ControllerHandler controllerHandler) {


        List<Method> requestMappingMethodList = new ArrayList<Method>(20);
        //在控制层，将mehtod 的权限符设置为public
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(RequestMapping.class)) {
                requestMappingMethodList.add(declaredMethod);
            }
        }

        Method[] resultArr = new Method[requestMappingMethodList.size()];
        controllerHandler.setMethodList(requestMappingMethodList);
        return requestMappingMethodList.toArray(resultArr);
    }


    /*
     * 解析方法信息，包括，入参信息，出参信息,注解信息
     */
    public List<HandlerMethod> getHandlerMethodsInfo(ClassLoader classLoader, String clazzName, ControllerHandler controllerHandler) throws Exception {

        Class<?> clazz = classLoader.loadClass(clazzName);

        List<HandlerMethod> handlerMethodList = new ArrayList<HandlerMethod>();
        HandlerMethod handlerMethod = null;
        //获取所有的方法
        Method[] declaredMethods = clazz.getDeclaredMethods();
        //根据方法做筛选
        for (Method declaredMethod : declaredMethods) {

            if (!declaredMethod.isAnnotationPresent(RequestMapping.class)) {
                continue;
            }
            //解析方法 设置controller,设置所属的方法，解析方法参数,解析返回体
            handlerMethod = new HandlerMethod(controllerHandler, declaredMethod);


            Annotation[] annotations = declaredMethod.getDeclaredAnnotations();
            for (Annotation annotation : annotations) {
                AnnotationAttributes annotationAttributes = (AnnotationAttributes) AnnotationUtils.getAnnotationAttributes(annotation);
                //设置url
                if (annotation instanceof RequestMapping) {
                    String path = (String) annotationAttributes.get("path");
                    handlerMethod.setUrl(path);
                }
                handlerMethod.addAnnotationAttributesMap(annotation, annotationAttributes);

            }
            handlerMethodList.add(handlerMethod);
        }

        return handlerMethodList;
    }


    public void parseMehtodParam(final Method method, HandlerMethod helperMethod) throws Exception {
        throw new UnsupportedOperationException();
    }

    public static Logger getLogger() {
        return logger;
    }

    public List<HandlerMethodArgumentResolver> getHandlerMethodArgumentResolvers() {
        return handlerMethodArgumentResolvers;
    }

    public void setHandlerMethodArgumentResolvers(List<HandlerMethodArgumentResolver> handlerMethodArgumentResolvers) {
        this.handlerMethodArgumentResolvers = handlerMethodArgumentResolvers;
    }

    public List<HandlerMethodReturnValueHandler> getHandlerMethodReturnValueHandlers() {
        return handlerMethodReturnValueHandlers;
    }

    public void setHandlerMethodReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlerMethodReturnValueHandlers) {
        this.handlerMethodReturnValueHandlers = handlerMethodReturnValueHandlers;
    }

    /*
     *  添加一些其他东西
     */

    /*
     * 添映射器
     */
    public void addHandlerMapping(HandlerMapping... mappings) {

        handlerMappings.addAll(Arrays.asList(mappings));

    }


    public List<HandlerMapping> getHandlerMappings() {
        return handlerMappings;
    }

    public void setHandlerMappings(List<HandlerMapping> handlerMappings) {
        this.handlerMappings = handlerMappings;
    }

    public List<HandlerAdapter> getHandlerAdapters() {
        return handlerAdapters;
    }

    public void setHandlerAdapters(List<HandlerAdapter> handlerAdapters) {
        this.handlerAdapters = handlerAdapters;
    }


    public List<View> getViewResolvers() {
        return viewResolvers;
    }

    public void setViewResolvers(List<View> viewResolvers) {
        this.viewResolvers = viewResolvers;
    }
}